﻿using System;
using System.Text;

namespace DimensionsHelper.SourceGeneration
{

    public sealed class SourceWriter
    {

        private readonly StringBuilder _builder = new StringBuilder();
        private const char IndentationChar = ' ';
        private const int DefaultIndentation = 4;
        private int _indentSpaceCount = -1;
        private int _indentLevel = -1;


        public int IndentSpaceCount
        {
            get => _indentSpaceCount < 0 ? DefaultIndentation : _indentSpaceCount;
            set => _indentSpaceCount = value;
        }


        public int IndentLevel
        {
            get => _indentLevel < 0 ? 0 : _indentLevel;
            set => _indentLevel = value;
        }


        public void Append(char c)
        {
            _builder.Append(c);
        }


        public void Append(string text)
        {
            _builder.Append(text);
        }


        private void AppendIndentation()
        {
            if (IndentLevel > 0)
            {
                _builder.Append(IndentationChar, IndentLevel * IndentSpaceCount);
            }
        }

        public void AppendLine(char ch)
        {
            AppendIndentation();
            _builder.Append(ch);
            _builder.AppendLine();
        }


        public void AppendLine()
        {
            _builder.AppendLine();
        }


        public void AppendLine(string text)
        {
            if (IndentLevel == 0)
            {
                _builder.AppendLine(text);
                return;
            }

            var span = text.AsSpan();
            bool isLastLine;
            do
            {
                var line = GetLineFromSpan(ref span, out isLastLine);

                AppendIndentation();
                _builder.Append(line.ToString());
                _builder.AppendLine();

            } while (!isLastLine);
        }


        private static ReadOnlySpan<char> GetLineFromSpan(ref ReadOnlySpan<char> remaining, out bool isLastLine)
        {
            if (remaining.IsEmpty)
            {
                isLastLine = true;
                return default;
            }

            ReadOnlySpan<char> restText;

            int lfIndex = remaining.IndexOf('\n');
            // 最后一行
            if (lfIndex == -1)
            {
                lfIndex = remaining.Length;
                isLastLine = true;
                restText = default;
            }
            else
            {
                restText = remaining.Slice(lfIndex + 1);
                isLastLine = false;
            }

            if (lfIndex > 0 && remaining[lfIndex - 1] == '\r')
            {
                lfIndex--;
            }

            ReadOnlySpan<char> nextLine = remaining.Slice(0, lfIndex);
            remaining = restText;
            return nextLine;
        }


        public void Clear()
        {
            _builder.Clear();
            _indentLevel = 0;
        }


        public override string ToString()
        {
            return _builder.ToString();
        }

    }

}